The Dead End of iOS

📅
⏱️ 4 min read (624 words)

"iOS's so-called tombstone mechanism is a sign of backwardness, fitting only a backward national context."

Android’s four-component framework is built entirely on OOP principles—its design is leagues ahead. iOS’s architecture, by contrast, simply inherits the Unix tradition: the containers now ubiquitous on Linux are converging with Android apps—various kinds of namespace isolation—though without bytecode yet; iOS’s background mechanism is nothing more than daemon processes.

What OOP offers is the abstraction of objects as a kind of persistent callback. Anyone who has written Java knows that the most infuriating thing is the endless tower of inheritance—yet that is also where OOP’s real power lies. Android’s base component classes implement lifecycle functions; by inheriting from them, a system takes full control over the lifecycle of every large and small component within an app.

iOS, on the other hand—or rather XNU, the kernel behind all Apple OSes—is architecturally perverse. At the bottom sits the advanced XNU microkernel, with message-passing and full isolation between kernel and user address spaces; above it run system components like the WindowManager, which one might charitably defend under the theory that only living software has bugs; then there is the split between the BSD API and Mac Catalyst—two entirely different worlds—and Metal API feels like the difference between silicon-based and carbon-based life compared to OpenGL or Vulkan. Here one has to praise Windows NT: because it strives not, nothing in the world can strive against it; a modern kernel whose design was essentially complete around 2000, requiring only minor patches to this day. Apple’s OSes carry far more historical baggage than Windows.

So we can see how misleading iOS’s “tombstone mechanism” really is. The tombstone supposedly saves a handle to the application’s suspended state—yet apps come back to life, so it might as well be called a condom, used during sleep and thrown away after. But wait—in operating system theory, what is the thing that saves application state called? The Process Control Block! So what is the real difference between a tombstone and a PCB/TCB? Where did the encapsulation role the OS is supposed to provide go? Where is the much-vaunted microkernel advantage of “separating mechanism from policy”?

If I were designing this: on macOS, apps exist as binary files and have inherently lost the possibility of OS-managed lifecycles. One should therefore, following native UI programs, implement process isolation; and following today’s systemd or launchd, implement a system-managed configuration file for controlling service startup and shutdown. That would use data to control the lifecycle—comparable to Android’s programmatic lifecycle control, with neither approach clearly superior.

In fact, the modern unified Apple platform programming toolkit, SwiftUI, has already converged with Android Jetpack in essence: both are reactive UI frameworks using Effects to update the data-driven UI; Swift apps also have lifecycle callbacks.

As for Android’s background mechanisms—or the methods power users use to control background apps—there are two approaches: blocking launches and scheduling. Blocking launches is well-known: either block via IFW, or disable components through APIs like Knox. Scheduling is more varied: a Service may be running, suspended in memory, swapped to virtual memory, or killed entirely; in addition, there are Process and Application—three layers in all. Different scheduling apps coin different names: “well-behaved,” “frozen,” “synced”—a dazzling variety; truly spectacular.

Currently using Thanox. The UI design is perfect; beyond that, the feature structure is reasonably clear. But the truly effective, long-lasting solution is to merge this kind of mechanism into AOSP itself. Android’s appeal lies precisely in fine-grained control of one’s own device—and that is what we need. Who, then, rules this city today?